﻿using System;

namespace TfsUtils.Ui.Navigation
{
	public interface IBroker
	{
		/// <summary>
		/// registra per un certo tipo di messaggio una azione da intraprendere.
		/// Praticamente un chiamante può dire al brocker, ogni volta che ti arriva
		/// un messaggio di tipo T io voglio che mi passi il suo contenuto
		/// </summary>
		/// <typeparam name="T">Il tipo di dato che serve anche a discriminare il messaggio</typeparam>
		/// <param name="action">L'azione da chiamare.</param>
		void RegisterForMessage<T>(Action<Message<T>> action);

		/// <summary>
		/// Questo è il messaggio.
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="message"></param>
		void SendMessage<T>(Message<T> message);

		/// <summary>
		/// 
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="action"></param>
		void UnRegisterForMessage<T>(Action<Message<T>> action);

		/// <summary>
		/// Dichiaro che sono in grado di gestire un messaggio che contiene un 
		/// dato di tipo T e torno un TRet. Per comodità è possibile registrare solamente
		/// un messaggio con tipo di ritorno.
		/// </summary>
		/// <typeparam name="T">Il tipo di dato del messaggio.</typeparam>
		/// <typeparam name="TRet">Il tipo del valore di ritorno</typeparam>
		/// <param name="commandName">Il nome del messaggio per disambiguare il comando
		/// che viene supportato.</param>
		/// <param name="func">La funzione che deve essere chiamata</param>
		void RegisterForOperation<T, TRet>(String commandName, Func<T, TRet> func);

		/// <summary>
		/// La differenza con <see cref="Broker.SendMessage{T}"/> è che in questo caso io sto 
		/// richiedendo una risposta, per cui mi attendo che se qualcuno si è registrato
		/// per questa tipologia di messaggio io sia in grado di ricevere una risposta
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <typeparam name="TU"></typeparam>
		/// <param name="message"></param>
		/// <returns></returns>
		Response<T> Request<T, TU>(Request<TU> message);

	    /// <summary>
	    /// Si registra per un messaggio ma passa un token che può essere utilizzato per 
	    /// deregistrare tutti gli handler associati.
	    /// </summary>
	    /// <typeparam name="T"></typeparam>
	    /// <param name="action">The action.</param>
	    /// <param name="token">The token.</param>
	    /// <param name="executeInUiThread">Richiede al broker che questi messaggi vengano lanciati
	    /// nel thread principale.</param>
	    void RegisterForMessage<T>(Action<Message<T>> action, Object token, Boolean executeInUiThread);

        /// <summary>
        /// Deregistra tutti i message handler legati a questo token.
        /// </summary>
        /// <param name="token">The token.</param>
	    void UnRegisterAll(object token);
	}
}